#include "EventLoop.h"
#include <unistd.h>
#include <sys/epoll.h>
#include <stdio.h>
#include <iostream>
#include <utility>
#include "json.hpp"
#include "string.h"
#include "sstream"
using std::cerr;
using std::cout;
using std::endl;
using json = nlohmann::json;

EventLoop::EventLoop(Sender &sender)
: _epfd(createEpollFd())
, _isLooping(false)
, _sender(sender)
, _evtList(1024)
, _conn(sender.fd())
{
    //将listenfd放在红黑树上进行监听
    addEpollReadFd(_sender.fd());
    addEpollReadFd(STDIN_FILENO);
}

EventLoop::~EventLoop()
{
    close(_epfd);
}

//是否循环
void EventLoop::loop()
{
    _isLooping = true;
    _sender.sockConnect();
    while(_isLooping)
    { 
        waitEpollFd();
    }
}

void EventLoop::unloop()
{
    _isLooping = false;
}


//执行epoll_wait的函数
void EventLoop::waitEpollFd()
{
    int nready;
    do
    {
        nready = epoll_wait(_epfd, &*_evtList.begin(), _evtList.size(), -1);
    }while(-1 == nready && errno == EINTR);

    if(-1 == nready)
    {
        cerr << "-1 == nready " << endl;
        return;
    }
    else
    {
        for(int idx = 0; idx < nready; ++idx)
        {
            
            int fd = _evtList[idx].data.fd;
            if(fd == STDIN_FILENO){
                handleInput();    
            }
            else{
                handleMessage();  
            }
          
        }
    }
}

//处理消息的发送
void EventLoop::handleInput()
{
    char buf[65535];
    memset(buf, 0, sizeof(buf));
    int sret = read(STDIN_FILENO, buf, sizeof(buf));
    //cout << sret << endl;
    string bufString(buf);
    bufString = bufString.substr(0,bufString.size() - 1);
    //cout << bufString << endl;

    string command,data;
    std::istringstream iss(bufString);
    iss >> command;
    //cout << command << endl; 
    data = bufString.substr(command.size() + 1);
    //cout << data << endl;
    json jsonString;
    jsonString["command"] = command;
    jsonString["data"] = data;
    _conn.send(jsonString.dump() + "\n");
    //_conn.send(bufString);   
}

void EventLoop::handleMessage()
{
    string msg = _conn.receive();
    msg = msg.substr(0, msg.size() - 1);
    if(msg == "rec"){
        msg = _conn.receive();
        msg = msg.substr(0, msg.size() - 1);
        cout << msg << endl;

    }
    else{
        msg = _conn.receive();
        msg = msg.substr(0, msg.size() - 1);
        if(msg == "false"){
        cout << "未查询到相关网页" << endl;
        }
        else{
            json jsonArray = json::parse(msg);
            for (auto& jsonObject : jsonArray) {
                // 读取 JSON 对象的值
                int id = jsonObject["id"];
                string title = jsonObject["title"];
                string URL = jsonObject["URL"];
                string summary = jsonObject["summary"];

                // 输出读取的值
                cout << "ID: " << id << endl;
                cout << "Title: " << title << endl;
                cout << "URL: " << URL << endl;
                /* string highlightedSummary = highlightKeyword(summary, keyword); */
                cout << "summary: " << summary << endl;
                cout << endl; // 用于分隔每个 JSON 对象
            }             
        }
    }    
}

//创建文件描述符epfd
int EventLoop::createEpollFd()
{
    int fd = epoll_create(1);
    if(fd < 0)
    {
        perror("epoll_create");
        return fd;
    }
    return fd;
}

//将文件描述符放在红黑树上进行监听
void EventLoop::addEpollReadFd(int fd)
{
    struct epoll_event evt;
    evt.data.fd = fd;
    evt.events = EPOLLIN;

    int ret = epoll_ctl(_epfd, EPOLL_CTL_ADD, fd, &evt);
    if(ret)
    {
        perror("addEpollReadFd");
        return;
    }
}

//将文件描述符从红黑树上删除
void EventLoop::delEpollReadFd(int fd)
{
    struct epoll_event evt;
    evt.data.fd = fd;
    evt.events = EPOLLIN;

    int ret = epoll_ctl(_epfd, EPOLL_CTL_DEL, fd, &evt);
    if(ret)
    {
        perror("delEpollReadFd");
        return;
    }
}

/* string highlightKeyword(const string& text, const string& keyword) {
    string highlightedText = "";  // ANSI 黄色转义序列
    size_t pos = 0;
    while (true) {
        std::size_t found = text.find(keyword, pos);
        if (found != string::npos) {
            // 添加关键字之前的部分
            highlightedText += text.substr(pos, found - pos);
            // 添加带颜色的关键字
            highlightedText += "\033[31m" + keyword + "\033[0m";
            pos = found + keyword.length();
        } else {
            // 添加剩余的部分
            highlightedText += text.substr(pos);
            break;
        }
    }
    return highlightedText;
} */
